package hasthi.container;

import hasthi.common.BaseContext;
import hasthi.common.HasthiException;
import hasthi.common.Utils;
import hasthi.common.XmlBeanUtils;
import hasthi.common.HasthiException.FaultCode;
import hasthi.common.constants.HasthiConstants;
import hasthi.container.p2p.XmlMesssage;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;

import javax.wsdl.Fault;
import javax.xml.namespace.QName;

import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.w3.x2003.x05.soapEnvelope.EnvelopeDocument;

import xsul.invoker.soap_over_http.SoapHttpDynamicInfosetInvoker;

public class ContainerUtils {

    public static final QName WSA_ACTION = new QName("http://www.w3.org/2005/08/addressing",
            "Action");
    public static final QName WSA_TO = new QName("http://www.w3.org/2005/08/addressing", "To");
    public static final QName WSA_REPLY_TO = new QName("http://www.w3.org/2005/08/addressing",
            "ReplyTo");
    public static final QName WSA_MESSAGEID = new QName("http://www.w3.org/2005/08/addressing",
            "MessageID");
    public static final QName WSA_RELATES_TO = new QName("http://www.w3.org/2005/08/addressing",
            "RelatesTo");
    
//    private static ThreadLocal<Map<String, String>> threadLocal = new ThreadLocal<Map<String, String>>();
//    static{
//        threadLocal.set(new HashMap<String, String>(2));
//    }

    /**
     * supported oath format is hasthi/forward/<protocol>_<host>_<port>/<path>
     * 
     * @param path
     * @return
     */
    public static String getForwardUrl(String path) {
        Matcher matcher = HasthiConstants.FORWARD_HTML_PATTERN.matcher(path);
        if (matcher.matches()) {
            String fowardhost = matcher.group(1);
            String[] tokens = fowardhost.split("_");

            if (tokens.length == 3) {
                StringBuffer buf = new StringBuffer();
                buf.append(tokens[0]).append("://").append(tokens[1]).append(":").append(tokens[2])
                        .append("/").append(matcher.group(2));
                return buf.toString();
            }
        }
        return null;
    }

    /**
     * 
     * @param path
     * @param out
     * @return true if request has been served already
     * @throws HasthiException
     */
    public static boolean handleFileRequests(String path, OutputStream out) throws HasthiException {
        try {
            File file = findFile2Serve(path);
            if (file != null) {
                Utils.readAndWriteFileToOutputStream(file, out);
                return true;
            }
            return false;
        } catch (IOException e) {
            throw new HasthiException(e, FaultCode.InvaliedRequest);
        }
    }

    public static File findFile2Serve(String path) throws HasthiException {
        Matcher matcher = HasthiConstants.PUBLIC_HTML_PATTERN.matcher(path);
        if (matcher.matches()) {
            File file = new File("resources/public_html/" + matcher.group(1));
            if (file.exists()) {
                return file;
            }
        }
        return null;
    }
    
    
    public static String doUrlGet(BaseContext baseContext,String url) throws HasthiException{
        SoapHttpDynamicInfosetInvoker invoker;
        if(url.startsWith("https")){
            invoker = SoapContainer.createSecureInvoker(baseContext,null);
        }else{
            invoker = new SoapHttpDynamicInfosetInvoker();
        }
        return invoker.invokeHttpGet(url);
    }
    
    
    public static MessageContext buildMessageContextFromXBeansMessage(XmlObject soapRequest,String requestPath) throws HasthiException{
        if(soapRequest instanceof EnvelopeDocument){
            final XmlMesssage messsage = new XmlMesssage((EnvelopeDocument)soapRequest);
            XmlObject request = messsage.getBodyContent();
            return new SimpleMessageContext(request,requestPath,messsage.getAction());
        }else if(soapRequest instanceof org.xmlsoap.schemas.soap.envelope.EnvelopeDocument){
            XmlCursor c = ((org.xmlsoap.schemas.soap.envelope.EnvelopeDocument)soapRequest).getEnvelope().getHeader().newCursor();
            Map<QName, Object> headers = XmlBeanUtils.extractProperties(c,true);
            c.dispose();
            
            Object actionObj = headers.get(ContainerUtils.WSA_ACTION);
            String soapAction;
            
            if(actionObj != null){
                soapAction = XmlMesssage.findURIValue(actionObj);    
            }else{
                soapAction =  "";
            }
            return new SimpleMessageContext(XmlBeanUtils.extractBodyContent(soapRequest),requestPath,soapAction);
        }else{
            throw new HasthiException("Only support Soap Messages",FaultCode.InvaliedRequest);
        }
        

    }
    
//    public static void setToThreadLocal(String value,String key){
//        threadLocal.get().put(key, value);
//    }
//    
//    public static void getFromThreadLocal(String value,String key){
//        threadLocal.get().put(key, value);
//    }
}
